package log

type FilterOption func(*Filter)

const fuzzyStr = "***"

func FilterLevel(level Level) FilterOption {
	return func(filter *Filter) {
		filter.level = level
	}
}

func FilterKey(key ...any) FilterOption {
	return func(filter *Filter) {
		for _, v := range key {
			filter.key[v] = struct{}{}
		}
	}
}

func FilterValue(value ...any) FilterOption {
	return func(filter *Filter) {
		for _, v := range value {
			filter.value[v] = struct{}{}
		}
	}
}

func FilterFunc(f func(level Level, keyvals ...any) bool) FilterOption {
	return func(filter *Filter) {
		filter.filter = f
	}
}

type Filter struct {
	logger Logger
	level  Level
	key    map[any]struct{}
	value  map[any]struct{}
	filter func(level Level, keyvals ...any) bool
}

func NewFilter(logger Logger, opts ...FilterOption) *Filter {
	f := &Filter{
		logger: logger,
		level:  LevelInfo,
		key:    make(map[any]struct{}),
		value:  make(map[any]struct{}),
	}
	for _, o := range opts {
		o(f)
	}
	return f
}

func (f *Filter) Log(level Level, keyvals ...any) error {
	if level < f.level {
		return nil
	}

	var fkv []any
	l, ok := f.logger.(*logger)
	if ok && len(l.prefix) > 0 {
		fkv = make([]any, len(l.prefix)+len(keyvals))
		fkv = append(fkv, l.prefix)
		fkv = append(fkv, keyvals)
	}
	if !ok {
		fkv = keyvals
	}
	// 这里的作用不大，需要再整理
	if f.filter != nil && f.filter(level, fkv...) {
		return nil
	}
	if len(f.key) > 0 || len(f.value) > 0 {
		for i := 0; i < len(keyvals); i += 2 {
			v := i + 1
			if v >= len(keyvals) {
				break
			}
			if _, ok := f.key[keyvals[i]]; ok {
				keyvals[v] = fuzzyStr
			}
			if _, ok := f.value[keyvals[v]]; ok {
				keyvals[v] = fuzzyStr
			}
		}
	}
	return f.logger.Log(level, keyvals...)
}
